package stv5;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.net.Socket;
import java.net.URLDecoder;

import stv5.abstracted.Connection;

public class STConnection implements Connection {
	
	private Socket myskt;
	private BufferedReader input;
	private PrintWriter output;

	public STConnection(Socket s) {
		myskt = s;
		try
		{
			input = new BufferedReader (
				new InputStreamReader( myskt.getInputStream() ));
			output = new PrintWriter( myskt.getOutputStream(), true );
		} catch (IOException e) {}
	}
	
	public boolean hasReceived() {
		try {
			return input.ready();
		} catch (IOException e) {
			return false;
		}
	}

	@Override
	public Request read() {
		// wait for their input
		while (!hasReceived()) {}
		
		// parse it
		String head = readLine();
		String body = "";
		
		// get the post body if it's a POST
		if (head.indexOf("POST") > -1) {
			// ignore headers, except for Content-Length
			String line = "-";
			String[] tmp;
			int contentLength = 0;				
			while (!"".equals(line.trim())) {
				line = readLine();
				tmp = line.split(": ");
				if (tmp.length == 2 && "Content-Length".equals(tmp[0])) {
					contentLength = Integer.parseInt(tmp[1].trim());
				}
			}		
			try {
				body = URLDecoder.decode( read(contentLength), "UTF-8" );
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			}		
		}
		
		return Request.parse( head, body );
	}
	
	/**
	 * Read a string of "length," or until EOF
	 * @param length
	 * @return
	 */
	public String read(int length) {
		char[] cbuf = new char[ length ];
		int off = 0, read = -1;
		while (length > 0) {
			try {
				read = input.read(cbuf, off, length);
				if (read < 0)
					break; // end of stream; return what we've got
				length -= read;
				off += read;
			} catch (IOException e) {
				// return whatever we've read?
				break;
			}
		}
		
		return new String(cbuf);
	}
	
	public String readLine() {
		try {
			return input.readLine();
		} catch (IOException e) {
			return "";
		}
	}

	@Override
	public boolean send(Response response) {
		response.writeHeaders( output );
		flush();
		if (response.isText())
			response.writeBody(output);
		else {
			try {
				myskt.getOutputStream().write( response.getBytes() );
			} catch (IOException e) {
				System.out.println("Couldn't write bytes");
				return false;
			}
		}
		
		return true;
	}

	@Override
	public boolean isLocal() {
		return myskt.getInetAddress().isLoopbackAddress();
	}

	@Override
	public void close() {
		try {
			myskt.close();
			input.close();
			output.close();
		} catch (IOException e) {}
	}

	@Override
	public void flush() {
		output.flush();
	}

}
